package com.snake.excel2java.excel.generator.file;

import java.io.File;
import java.io.FileOutputStream;

import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Component;

@Component
@NoArgsConstructor
@Slf4j
public class TypeCreator {
	public void generate() {
		
		File dir = new File("");

		String path = dir.getAbsoluteFile().getParentFile() + "/excel2java/";
		
		String excelDirPath = dir.getAbsoluteFile().getParentFile() + "/excels/type/";

		File exceldir = new File(excelDirPath);
		
		if(!exceldir.isDirectory())
			exceldir.mkdirs();
		
		log.info("generate java file from dir: {}", excelDirPath);
		
		String excel2JavaPath = path + "\\src\\main\\java\\com\\snake\\excel2java\\excel\\type\\";
		
		File excel2JavaPathDir = new File(excel2JavaPath);
		
		if(!excel2JavaPathDir.isDirectory())
			excel2JavaPathDir.mkdirs();
		
		for(File file: excel2JavaPathDir.listFiles()) 
			if(file.isFile())
				file.delete();
		
		for(File file: exceldir.listFiles()) {
			
			if(file.isFile()) {
				
				if(file.getName().startsWith("~"))
					continue;
				
				String[] type = readTypeExcel(file, 1);
				String[][] value = readExcel(file, 2, type[1]);
				
				generateEnumFile(excel2JavaPath, file.getName(), type[1], value, 2);
			}
			
		}

	}
	
	public void generateEnumFile(String excel2JavaPath, String filename, String type, String[][] value, int index) {
		
		if(type.equals("string"))
			type = "String";
		
		String javaFilename = filename.substring(0, 1).toUpperCase() + filename.substring(1, filename.indexOf(".")) + "Type";
		
		StringBuilder builder = new StringBuilder();
		
		builder.append("package com.snake.excel2java.excel.type;\r\n\r\n")
			   .append("public enum ")
			   .append(javaFilename)
			   .append(" {\r\n\r\n");
		
		int length = value.length;
		
		int dataLen = index;
		for(int i = index; i < length; ++i) {
			
			String[] temp = value[i];
			
			if(null == temp[0] || temp[0].isEmpty())
				continue;
			
			dataLen++;
		}
		
		for(int i = index; i < length; ++i) {
			
			String[] temp = value[i];
			
			if(null == temp[0] || temp[0].isEmpty())
				continue;
			
			if(i == index && type.equals("int")) {
				
				builder.append("\tSTART(")
					   .append(Integer.parseInt(temp[1]) - 1)
					   .append("),\r\n");
				
			}
			
			builder.append("\t")
				   .append(temp[0])
				   .append("(");
			
			if(type.equals("String"))
				builder.append("\"");
			
			builder.append(temp[1]);
			
			if(type.equals("String"))
				builder.append("\"");
			
			builder.append(")");
			
			if(i == dataLen - 1) {
				
				if(!type.equals("int")) 
					builder.append(";");
				else 
					builder.append(",");
				
				
			} else 
				builder.append(",");
			
			builder.append("\t\t\t// ")
				   .append(temp[2])
				   .append("\r\n");
			
			if(i == dataLen - 1 && type.equals("int")) {
				
				builder.append("\tEND(")
				   .append(Integer.parseInt(temp[1]) + 1)
				   .append(");");
			}

		}
		
		builder.append("\r\n\r\n")
			   .append("\tprivate ")
			   .append(type)
			   .append(" value;\r\n");
		
		builder.append("\tprivate ")
			   .append(javaFilename)
			   .append("(")
			   .append(type)
			   .append(" value) { \r\n")
			   .append("\t\tthis.value = value;\r\n")
			   .append("\t}\r\n\r\n")
			   .append("\tpublic ")
			   .append(type)
			   .append(" getValue() {\r\n")
			   .append("\t\treturn value;\r\n")
			   .append("\t}\r\n\r\n");
//			   .append("\tpublic void setValue(")
//			   .append(type)
//			   .append(" value) {\r\n")
//			   .append("\t\tthis.value = value;\r\n")
//			   .append("\t}\r\n\r\n");
		
		
		builder.append("\tpublic static ")
			.append(javaFilename)
			.append(" get(")
			.append(type)
			.append(" value) {\r\n\r\n")
			.append("\t\tswitch (value) {\r\n");
		
		for(int i = index; i < length; ++i) {
			
			String[] temp = value[i];
			
			if(null == temp[0] || temp[0].isEmpty())
				continue;
			
			if(type.equals("String")) {
				
				builder.append("\t\tcase \"")
				.append(temp[1])
				.append("\":\r\n")
				.append("\t\t\treturn ")
				.append(temp[0])
				.append(";\r\n");	
				
			} else {
				
				builder.append("\t\tcase ")
				.append(temp[1])
				.append(":\r\n")
				.append("\t\t\treturn ")
				.append(temp[0])
				.append(";\r\n");	
				
			}
			
	
			
		}
		
		if(type.equals("String")) {
			
			builder.append("\t\t}\r\n\r\n")
			.append("\t\treturn null;\r\n")
			.append("\t}\r\n")
			.append("}");
			
		} else {
			
			builder.append("\t\t}\r\n\r\n")
			.append("\t\treturn END;\r\n")
			.append("\t}\r\n")
			.append("}");
		}
		
		

		
		
		File javaFile = new File(excel2JavaPath + "\\" + javaFilename + ".java");
		
		try {
			FileOutputStream fout = new FileOutputStream(javaFile);
			
			fout.write(builder.toString().getBytes("UTF-8"));
			fout.close();
			
			log.info("\r\n\r\n--------------------- write file {} success ---------------------", javaFile.getAbsolutePath());
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			
			log.error("--------------------- write file error: {} ---------------------", e.getMessage());

			e.printStackTrace();
		}
		
	}
	
	public String[][] readExcel(File file, int startLine, String type) {
		
		log.info("\r\n\r\n\r\n------------- read {} --------------\r\n", file.getName());
		
		XSSFWorkbook workbook2007 = null;
		
		String[][] result = null;
		int i = startLine;
		try {
			
			workbook2007 = new XSSFWorkbook(file);
			XSSFSheet sheet = workbook2007.getSheetAt(0);
			
//			FormulaEvaluator evaluator = sheet.getWorkbook()
//					  .getCreationHelper()
//					  .createFormulaEvaluator();  
//			evaluator.evaluateAll();
			
			int length = sheet.getLastRowNum() + 1;
			result = new String[length][3];
			
			for( ; i < length; ++i) {
				
				XSSFRow row = sheet.getRow(i);//类型
				
				if(null == row)
					continue;
				
				result[i][0] = readString(row, 0, type);
				result[i][1] = readString(row, 1, type);
				result[i][2] = readString(row, 2, type);
				
				log.info("------------- reads row {}, {}, {}, {}", i, result[i][0], result[i][1], result[i][2]);
			}
			
			
			workbook2007.close();
			
		} catch (Exception e) {
			
			log.error("\r\n\r\n------------- read error in row {} --------------\r\n\r\n", i);
			log.error(e.toString());
			
			e.printStackTrace();
			
		} finally {
			
		}
		
		
		return result;
	}
	
	// 1
	public String[] readTypeExcel(File file, int startLine) {
		
		log.info("\r\n\r\n\r\n------------- read {} --------------\r\n", file.getName());
		
		XSSFWorkbook workbook2007 = null;
		
		String[] result = new String[3];
		try {
			
			workbook2007 = new XSSFWorkbook(file);
			XSSFSheet sheet = workbook2007.getSheetAt(0);

			
			XSSFRow row = sheet.getRow(startLine);//类型
			
			result[0] = readString(row, 0, "string");
			result[1] = readString(row, 1, "string");
			result[2] = readString(row, 2, "string");
			
			
			workbook2007.close();
			
		} catch (Exception e) {
			
			log.error("\r\n\r\n------------- read error in row {} --------------\r\n\r\n", startLine);
			log.error(e.toString());
			
			e.printStackTrace();
			
		} finally {
			
		}
		
		
		return result;
	}

	public static final String EMPTY = "";
	protected String readString(XSSFRow row, int index, String type) {
		
		try {
			XSSFCell cell = row.getCell(index);
			
			if(null == cell)
				return "";
			
			CellType cellType = cell.getCellType();
			
			switch (cellType) {
			case BLANK:
				
				return EMPTY;
				
			case BOOLEAN:
			
				return EMPTY + cell.getBooleanCellValue();
				
			case NUMERIC:
				
				switch (type) {
				case "int":
					
					return EMPTY + Double.valueOf(cell.getNumericCellValue()).intValue();
				case "float":
					
					return EMPTY + Double.valueOf(cell.getNumericCellValue()).floatValue();
				case "double":
				default:
					return EMPTY + cell.getNumericCellValue();
				}

			default:
				break;
			}
			
			String value = cell.getStringCellValue();
			
			if(null == value)
				return "";
			
			return value.trim();
			
		} catch (Exception e) {
			e.printStackTrace();
			log.error("string - read column {} error in row {}......", index, row.getRowNum());
		}
		
		return EMPTY;
	}

}
